﻿using LJ.Abstractions.Exceptions;
using LJ.Abstractions.Extensions;
using LJ.WebApi.Abstractions;
using LJ.WebApi.Data;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;

namespace LJ.WebApi.Mvc.Filters;


/// <summary>
/// 规范化结构（请求异常）过滤器
/// </summary>
public class UnifyExceptionFilter : IAsyncExceptionFilter, IOrderedFilter
{
    /// <summary>
    /// 排序属性
    /// </summary>
    public int Order => 8888;

    public async Task OnExceptionAsync(ExceptionContext context)
    {
        if (context.ExceptionHandled == false)
        {
            var result = new WebApiResult<object>();

            var logger = context.HttpContext.RequestServices.GetLogger<UnifyExceptionFilter>();

            var webApiExceptionHandlers = context.HttpContext.RequestServices.GetServices<IWebApiExceptionHandler>();
            foreach (var webApiExceptionHandler in webApiExceptionHandlers.OrderBy(a=>a.Seq))
            {
                await webApiExceptionHandler.ExecuteAsync(context.HttpContext.RequestServices, context.Exception);
            }

            if (context.Exception is FriendlyException friendlyException)
            {
                logger.LogInformation("【规范化结构（请求异常）】: \r\n {Message}", friendlyException);
                result.Succeeded = false;
                result.StatusCode = string.IsNullOrEmpty(friendlyException.StatusCode) ? StatusCodes.Status500InternalServerError.ToString() : friendlyException.StatusCode;
                result.Message = friendlyException.Message;
            }
            else
            {
                logger.LogError("【规范化结构（请求异常）】: \r\n {Message}", context.Exception);
                result.Succeeded = false;
                result.StatusCode = StatusCodes.Status500InternalServerError.ToString();
                result.Message = context.Exception.Message;
            }
            context.Result = new ObjectResult(result);
            context.HttpContext.Response.StatusCode = StatusCodes.Status200OK;
            context.ExceptionHandled = true;
        }
    }
}
